use leptos::*;

#[component]
fn App() -> impl IntoView {
    view! {
        <div>
            <Counter />
            <TopNewsV1 />
            <TopNewsV2 />
            <TopNewsV3 />
            <TopNewsV4 />
        </div>
    }
}

#[component]
fn Counter() -> impl IntoView {
    let (value, set_value) = create_signal(0);

    let reset = move |_| set_value.set(0);
    let decrement = move |_| set_value.update(|value| *value -= 1);
    let increment = move |_| set_value.update(|value| *value += 1);
    view! {
        <p class:red=move || value.get() % 2 == 1>
            <strong>"响应式: "</strong>
            // you can insert Rust expressions as values in the DOM
            // by wrapping them in curly braces
            // if you pass in a function, it will reactively update
            {move || value.get()}
        </p>
        <p class=("green", move || value.get() % 2 == 0)>
            <strong>"响应式简洁写法: "</strong>
            // signals are functions, so we can remove the wrapping closure
            {value}
        </p>
        <p>
            <strong>"非响应式: "</strong>
            // NOTE: if you write {count()}, this will *not* be reactive
            // it simply gets the value of count once
            {value.get()}
        </p>
        <ProgressBar max=30 value=value />
        <button on:click=decrement>"点击减1"</button>
        <button on:click=reset>"数值重置"</button>
        <button on:click=increment>"点击加1"</button>
    }
}

#[component]
fn ProgressBar(
    #[prop(default = 10)]
    max: u16,
    #[prop(into)]
    value: Signal<i64>,
) -> impl IntoView {
    let double_count = move || value.get() * 2;
    view! {
        <div>
            <strong>"double count: "</strong>
            {double_count}
        </div>
        <div>
            <progress max=max value=double_count />
        </div>
    }
}

#[component]
fn TopNewsV1() -> impl IntoView {
    let news = vec![
        "news 1",
        "news 2",
        "news 3"
    ];
    view! {
        <p>iter v1</p>
        <ul>{news.into_iter().map(|element| view! { <li>{element}</li> }).collect::<Vec<_>>()}</ul>
    }
}

#[component]
fn TopNewsV2() -> impl IntoView {
    let news = vec![
        "news 1",
        "news 2",
        "news 3"
    ];
    view! {
        <p>iter v2</p>
        <ul>{news.into_iter().map(|element| view! { <li>{element}</li> }).collect_view()}</ul>
    }
}

#[component]
fn TopNewsV3() -> impl IntoView {
    let news = vec![
        "news 1",
        "news 2",
        "news 3"
    ];
    let news_view = news.into_iter()
        .map(|element| {
            view! { <li>{element}</li> }
        }).collect::<Vec<_>>();
    view! {
        <p>iter v3</p>
        <ul>{news_view}</ul>
    }
}

#[component]
fn TopNewsV4() -> impl IntoView {
    let news = vec![
        "news 1",
        "news 2",
        "news 3"
    ];
    let news_view = news.into_iter()
        .map(|element| {
            view! { <li>{element}</li> }
        }).collect_view();
    view! {
        <p>iter v4</p>
        <ul>{news_view}</ul>
    }
}

fn main() {
    console_error_panic_hook::set_once();
    mount_to_body(|| view! { <App /> })
}
